package com.j4cf.web.controller;

import com.baidu.unbiz.fluentvalidator.ComplexResult;
import com.baidu.unbiz.fluentvalidator.FluentValidator;
import com.baidu.unbiz.fluentvalidator.ResultCollectors;
import com.j4cf.auth.service.AuthUserService;
import com.j4cf.auth.shiro.session.AuthSession;
import com.j4cf.auth.shiro.session.AuthSessionDao;
import com.j4cf.common.base.BaseController;
import com.j4cf.common.base.BaseResult;
import com.j4cf.common.base.BaseResultEnum;
import com.j4cf.common.util.RedisUtil;
import com.j4cf.common.validator.LengthValidator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Description:
 * @Author: LongRou
 * @CreateDate: 2018 2018/4/26 10:29 ,consumes = MediaType.APPLICATION_JSON_VALUE
 * @Version: 1.0
 **/
@RestController
@RequestMapping(value = "/sso")
@Api(value = "登录管理", description = "登录管理")
public class SSOController extends BaseController{
    private static final Logger LOGGER = LoggerFactory.getLogger(SSOController.class);
    // 全局会话key
    private final static String J4CF_SESSION_ID = "j4cf-session-id";
    // 全局会话key列表
    private final static String J4CF_SESSION_IDS = "j4cf-session-ids";
    // code key
    private final static String J4CF_CODE = "j4cf-code";

    @Autowired
    AuthUserService authUserService;

    @Autowired
    AuthSessionDao authSessionDao;

    @ApiOperation(value = "登录s")
    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public Object test(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
        return new BaseResult(BaseResultEnum.SUCCESS, "");
    }

    @ApiOperation(value = "登录")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Object login(@RequestBody Map<String, Object> params) {
        String username = (String) params.get("username");
        String password = (String) params.get("password");
        String rememberMe = (String) params.get("rememberMe");
        //信息校验
        ComplexResult result = FluentValidator.checkAll()
                .on(username, new LengthValidator(1, 30, "账号"))
                .on(password, new LengthValidator(5, 32, "密码"))
                .doValidate()
                .result(ResultCollectors.toComplex());
        if (!result.isSuccess()) {
            return new BaseResult(BaseResultEnum.ERROR, result.getErrors().get(0).getErrorMsg());
        }
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        String sessionId = session.getId().toString();
        // 判断是否已登录，如果已登录，则回跳，防止重复登录
        String hasCode = RedisUtil.get(J4CF_SESSION_ID + "_" + sessionId);
        // code校验值
        if (StringUtils.isBlank(hasCode)) {
            // 使用shiro认证
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
            try {
                if (BooleanUtils.toBoolean(rememberMe)) {
                    usernamePasswordToken.setRememberMe(true);
                } else {
                    usernamePasswordToken.setRememberMe(false);
                }
                subject.login(usernamePasswordToken);
            } catch (UnknownAccountException e) {
                return new BaseResult(BaseResultEnum.ERROR, "帐号不存在！");
            } catch (IncorrectCredentialsException e) {
                return new BaseResult(BaseResultEnum.ERROR, "密码错误！");
            } catch (LockedAccountException e) {
                return new BaseResult(BaseResultEnum.ERROR, "帐号已锁定！");
            }
            // 更新session状态
            authSessionDao.updateStatus(sessionId, AuthSession.OnlineStatus.on_line);
            // 全局会话sessionId列表，供会话管理
            RedisUtil.lpush(J4CF_SESSION_IDS, sessionId.toString());
            // 默认验证帐号密码正确，创建code
            String code = UUID.randomUUID().toString();
            // 全局会话的code
            RedisUtil.set(J4CF_SESSION_ID + "_" + sessionId, code, (int) subject.getSession().getTimeout() / 1000);
            // code校验值
            RedisUtil.set(J4CF_CODE + "_" + code, code, (int) subject.getSession().getTimeout() / 1000);
        }
        // 回跳登录前地址
        Map<String,String> map  = new HashMap<String,String>();
        String backurl = (String) params.get("backurl");
        map.put("token",sessionId.toString());
        map.put("backurl",backurl);
        return new BaseResult(BaseResultEnum.SUCCESS, map);
    }

    @ApiOperation(value = "退出登录")
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public Object logout(HttpServletRequest request) {
        // shiro退出登录
        SecurityUtils.getSubject().logout();
        return new BaseResult(BaseResultEnum.SUCCESS, "登出成功");
    }




}

